package main

import (
	"flag"
	"fmt"
	"github.com/jung-kurt/gofpdf"
	"math/rand"
	"strconv"
	"time"
)

type A4 struct {
	pdf *gofpdf.Fpdf

	// a4 paper size
	width  float64 // a4 210mm
	height float64 // a4 297mm

	border string
	log    bool

	// margin
	leftMargin   float64
	rightMargin  float64
	topMargin    float64
	bottomMargin float64

	// padding
	leftPadding   float64
	rightPadding  float64
	topPadding    float64
	bottomPadding float64

	// size per paper
	colsPerPaper int
	rowsPerPaper int

	colWidth      float64
	rowHeight     float64
	rowMultiplier float64 // default 1

	line int
}

func (a4 *A4) Add(text string) {
nextPage:

	a4.line++

	col := a4.line / a4.rowsPerPaper
	row := a4.line % a4.rowsPerPaper
	if row == 0 {
		row = a4.rowsPerPaper
		col -= 1
	}

	if col >= a4.colsPerPaper {
		fmt.Printf("add page\n")
		a4.pdf.AddPage()
		a4.line = 0
		goto nextPage
	}

	x := a4.leftMargin + float64(col)*a4.colWidth
	y := a4.topMargin + float64(row-1)*a4.rowHeight*(1+a4.rowMultiplier)

	a4.pdf.SetXY(x, y)
	if a4.log {
		fmt.Printf("line:%d, col:%d row:%d, x: %f, y: %f\n",
			a4.line,
			col, row,
			x, y,
		)
	}

	a4.pdf.CellFormat(
		a4.colWidth, a4.rowHeight,
		text,
		a4.border,
		0,
		"LM",
		false,
		0,
		"",
	)

}

func (a4 *A4) OutputAndClose(fn string) error {
	return a4.pdf.OutputFileAndClose(fn)
}

func NewA4(column int, rowHeight float64, rowMultiplier float64, fontSize float64) *A4 {
	if column == 0 {
		column = 1
	}
	if rowHeight == 0 {
		rowHeight = 20
	}
	if rowMultiplier == 0 {
		rowMultiplier = 1
	}

	a4 := A4{
		width:  210,
		height: 297,

		leftMargin:   20,
		rightMargin:  20,
		topMargin:    10,
		bottomMargin: 10,

		colsPerPaper:  column,
		rowHeight:     rowHeight,
		rowMultiplier: rowMultiplier,
	}

	a4.colWidth = (a4.width - a4.leftMargin - a4.rightMargin) / float64(column)
	a4.rowsPerPaper = int((a4.height - a4.topMargin - a4.bottomMargin + a4.rowHeight*a4.rowMultiplier) / (a4.rowHeight * (1 + a4.rowMultiplier)))

	a4.pdf = gofpdf.New(
		"P",
		"mm",
		"A4",
		"")

	a4.pdf.AddPage()
	a4.pdf.SetFont("Arial", "B", fontSize)

	return &a4
}

// generateProblem 生成一个在指定范围内的加减法问题
func generateProblem(maxNum int) string {
	// 随机选择加法或减法
	op := "+"
	if rand.Intn(2) == 0 {
		op = "-"
	}

	// 随机生成两个数字
	num1 := rand.Intn(maxNum + 1)
	if op == "+" {
		maxNum = maxNum - num1
	}
	num2 := rand.Intn(maxNum + 1)

	// 确保在做减法时不产生负数
	if op == "-" && num1 < num2 {
		num1, num2 = num2, num1
	}

	return fmt.Sprintf("%d %s %d = ", num1, op, num2)
}

func main() {
	border := flag.String("border", "", "specifies how the cell border will be drawn")
	size := flag.Bool("size", false, "print size of col and row")
	log := flag.Bool("log", false, "log the info")

	flag.Parse()

	// 设置随机种子
	rand.Seed(time.Now().UnixNano())

	a4 := NewA4(2, 16, 0.4, 24)
	a4.border = *border
	a4.log = *log

	numsOf100 := 19
	numsOf1000 := 5

	if *size {
		fmt.Printf("col: %d, row: %d\n", a4.colsPerPaper, a4.rowsPerPaper)
	}

	for i := 0; i < numsOf100; i++ {
		a4.Add(fmt.Sprintf("%s", generateProblem(100)))
	}

	for i := 0; i < numsOf1000; i++ {
		a4.Add(fmt.Sprintf("%s", generateProblem(1000)))
	}

	err := a4.OutputAndClose("100-" + strconv.FormatInt(time.Now().Unix(), 10) + ".pdf")
	if err != nil {
		fmt.Printf("err:%v\n", err)
	}
}
